#include "combobox.h"
#include <QXmlStreamReader>
#include <QDebug>

static RegisterElementType r("ComboBox", ComboBox());

ComboBox::ComboBox()
    :current_index_(0)
    ,current_text_("Empty")
    ,max_count_([](){return 0;})
{
    connect(this, &Element::keyEvent, this, &ComboBox::onKeyEvent);
}

bool ComboBox::copyFrom(const Element *e)
{
    const ComboBox *c = qobject_cast<const ComboBox*>(e);
    if(!c){
        qWarning() << Q_FUNC_INFO << "Copy Failed.";
        return false;
    }

    items_ = c->items_;
    model_fun_ = c->model_fun_;
    max_count_ = c->max_count_;
    current_index_ = c->current_index_;
    current_text_ = c->current_text_;

    return Element::copyFrom(c);
}

Element *ComboBox::clone() const
{
    ComboBox *c = new ComboBox();
    if(!c->copyFrom(this)){
        delete c;
        c = NULL;
    }
    return c;
}

void ComboBox::addItem(const QString &item)
{
    items_.append(item);
}

void ComboBox::setModel(ComboBox::ItemModelFun model, int max)
{
    model_fun_ = model;
    max_count_ = [max](){ return max; };

    if(current_index_<max&&current_index_>=0){
        current_text_ = model_fun_(current_index_);
    }
}

void ComboBox::setModel(ComboBox::ItemModelFun model, ComboBox::ItemModelCount count)
{
    model_fun_ = model;
    max_count_ = count;

    if(current_index_<count()&&current_index_>=0){
        current_text_ = model_fun_(current_index_);
    }
}

void ComboBox::setMaxCount(int max)
{
    max_count_ = [max](){ return max; };
}

int ComboBox::maxCount() const
{
    return max_count_?max_count_():0;
}

void ComboBox::setCurrentIndex(int index)
{
    current_index_ = index;
    if(!items_.isEmpty()&&current_index_>=items_.size()){
        current_index_ = items_.size() - 1;
    }else if(model_fun_ && index>=max_count_()){
        current_index_ = max_count_()-1;
    }

    if(current_index_<0){
        current_index_ = 0;
    }
    if(!items_.isEmpty()){
        current_text_ = items_[current_index_];
    }else if(model_fun_){
        current_text_ = model_fun_(current_index_);
    }

    emit currentIndexChanged(current_index_);
}

int ComboBox::currentIndex() const
{
    return current_index_;
}

void ComboBox::setCurrentText(const QString &text)
{
    current_text_ = text;
}

QString ComboBox::currentText() const
{
    return current_text_;
}

QRect ComboBox::sizeHint() const
{
    return QRect(rect_.x(), rect_.y(), 5, 1);
}

void ComboBox::paintEvent()
{
    if(hasFocus())
        writeText(rect(), current_text_, Color(255, 0, 0));
    else
        writeText(rect(), current_text_);
}

void ComboBox::onKeyEvent(int key, int value)
{
    if(!hasBindKey(key)){
        qWarning() << Q_FUNC_INFO << QString("Unknown key (%1,%2)").arg(key).arg(value);
        return;
    }

    int delta = value>0?1:-1;

    int size = 0;
    if(!items_.isEmpty()){
        size = items_.size();
    }else{
        size = max_count_();
    }

    if(size<=0){
        return;
    }

    current_index_ = (current_index_+delta+size) % size;

    if(!items_.empty()){
        current_text_ = items_[current_index_];
        update();
    }else if(model_fun_){
        current_text_ = model_fun_(current_index_);
        update();
    }

    emit currentIndexChanged(currentIndex());
}

bool ComboBox::loadXML(QXmlStreamReader &root, Context *context, Element::SkipType)
{
    Element::loadXML(root, context, StayAfterLoaded);
    QString name = root.name().toString();
    while(!(root.tokenType()==root.EndElement&&root.name()==name)){
        root.readNext();
        if(root.tokenType()==root.StartElement){
            if(root.name()=="Item"){
                addItem(root.readElementText());
            }else{
                root.skipCurrentElement();
            }
        }
    }
    return true;
}

QString ComboBox::getSignalSignature(const QString &name) const
{
    if(name=="currentIndexChanged"){
        return SIGNAL(currentIndexChanged(int));
    }else{
        return Element::getSignalSignature(name);
    }
}
